package jmine.tec.persist.schema.impl.parsers;

import java.sql.Types;
import java.util.regex.Matcher;

import jmine.tec.persist.schema.impl.elements.ColumnElement;
import jmine.tec.persist.schema.impl.elements.ColumnTypeElement;
import jmine.tec.persist.schema.impl.elements.Schema;

/**
 * Parser de colunas
 * 
 * @author lundberg
 */
public class ColumnParser extends AbstractSchemaElementParser<ColumnElement> {
    private static final int COLUMN_NAME_GROUP_INDEX = 1;

    private static final int COLUMN_TYPE_GROUP_INDEX = 2;

    private static final int NOT_NULL_GROUP_INDEX = 3;

    private static final int DEFAULT_VALUE_GROUP_INDEX = 4;

    private CompositeParser<ColumnTypeElement> typeParser;

    /**
     * Construtor
     * 
     * @param schema schema
     */
    public ColumnParser(Schema schema) {
        super("\\s*(\\w+)\\s+((?:(?:\\w+)|double precision)(?:\\((?:.*)\\))?)(?:\\s+(not\\s+null))?(?:\\s+default\\s+(\\d+|'.*'))?", schema);
        this.typeParser = new CompositeParser<ColumnTypeElement>();
        this.typeParser.addParser(new ColumnTypeParser(schema, Types.CHAR));
        this.typeParser.addParser(new ColumnTypeParser(schema, Types.VARCHAR));
        this.typeParser.addParser(new ColumnTypeParser(schema, Types.DATE)); // colisão com Types.TIME
        this.typeParser.addParser(new ColumnTypeParser(schema, Types.TIMESTAMP));
        this.typeParser.addParser(new ColumnTypeParser(schema, Types.FLOAT));
        this.typeParser.addParser(new ColumnTypeParser(schema, Types.DOUBLE));
        this.typeParser.addParser(new ColumnTypeParser(schema, Types.NUMERIC)); // colisão com Types.DECIMAL
        this.typeParser.addParser(new ColumnTypeParser(schema, Types.VARBINARY));
        this.typeParser.addParser(new ColumnTypeParser(schema, Types.BLOB));
        this.typeParser.addParser(new ColumnTypeParser(schema, Types.CLOB));
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public ColumnElement doParse(Matcher matcher) {
        String name = matcher.group(COLUMN_NAME_GROUP_INDEX);
        ColumnElement column = new ColumnElement(name, this.getSchema());
        column.setNullable(matcher.group(NOT_NULL_GROUP_INDEX) == null);
        column.setType(this.typeParser.parse(matcher.group(COLUMN_TYPE_GROUP_INDEX)));
        column.setDefaultValue(matcher.group(DEFAULT_VALUE_GROUP_INDEX));
        return column;
    }

}
